package com.starmark.gateway.project.provider.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.starmark.auth.common.dto.SecurityUser;
import com.starmark.core.framework.base.AbstractUniqueBaseService;
import com.starmark.core.framework.converter.ListToStringConverter;
import com.starmark.core.framework.util.BeanMapper;
import com.starmark.core.framework.util.RedisUtils;
import com.starmark.core.framework.vo.PageQueryVo;
import com.starmark.gateway.project.provider.dto.GatewayProjectDto;
import com.starmark.gateway.project.provider.entity.GatewayProject;
import com.starmark.gateway.project.provider.entity.GatewayProjectAdmin;
import com.starmark.gateway.project.provider.mapper.GatewayProjectMapper;
import com.starmark.gateway.project.provider.service.IGatewayProjectAdminService;
import com.starmark.gateway.project.provider.service.IGatewayProjectService;
import com.starmark.gateway.project.provider.vo.AuthOrgElementDto;
import com.starmark.gateway.project.provider.vo.GatewayProjectVo;
import ma.glasnost.orika.MapperFacade;
import ma.glasnost.orika.MapperFactory;
import ma.glasnost.orika.impl.DefaultMapperFactory;
import cn.hutool.core.util.StrUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 网关工程 服务实现类
 * </p>
 *
 * @author starmark
 * @since 2020-05-24
 */
@Service
public class GatewayProjectServiceImpl extends AbstractUniqueBaseService<GatewayProjectMapper, GatewayProject> implements IGatewayProjectService {

    private MapperFacade mapper;



    private final static String PROJECT_REDIS_KEY = "starmark:gateway:project:info:";

    @Autowired
    private IGatewayProjectAdminService projectAdminService;


    @Autowired
    private RedisUtils redisUtils;

    @Override
    public void buildPageSearch(Map<String, Object> params, QueryWrapper<GatewayProject> eWrapper) {
        if (params.get("keyword") != null && StrUtil.isNotEmpty(params.get("keyword") + "")) {
            eWrapper.like("name", params.get("keyword") + "");
        }

    }
    @Override
    public Page<GatewayProject> selectProjectPage(PageQueryVo pageQueryVo, SecurityUser securityUser) {
        Page<GatewayProject> page = new Page<>(pageQueryVo.getCurrPage(), pageQueryVo.getLimit());

        IPage<GatewayProject> pageResult = this.getBaseMapper().selectProjectPage(page, securityUser);
        page.setRecords(pageResult.getRecords());
        page.setTotal(pageResult.getTotal());
        return page;
    }

    @Override
    public void overload() {
        List<GatewayProject> gatewayProjectList = this.list();
        gatewayProjectList.forEach(this::setProjectRedisKey);
    }

    private void setProjectRedisKey(GatewayProject gatewayProject){
        GatewayProjectDto projectDto=this.getProjectBeanMapper().map(gatewayProject, GatewayProjectDto.class);
        redisUtils.set(PROJECT_REDIS_KEY + projectDto.getProjectCode(), JSONObject.toJSONString(projectDto));

    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public GatewayProjectVo saveOrUpdateProject(GatewayProjectVo gatewayProjectVo) {
        GatewayProject gatewayProject = BeanMapper.map(gatewayProjectVo, GatewayProject.class);
        this.saveOrUpdate(gatewayProject);
        this.saveOrUpdateProjectAdmin(gatewayProject.getId(), gatewayProjectVo.getAdmins());
        gatewayProjectVo.setId(gatewayProject.getId());
        this.setProjectRedisKey(gatewayProject);
         return gatewayProjectVo;
    }

    private void saveOrUpdateProjectAdmin(String projectId,List<AuthOrgElementDto> admins ){
        projectAdminService.deleteProjectAdmins(projectId);
       if(CollectionUtils.isNotEmpty(admins)){
           List<GatewayProjectAdmin>  projectAdmins=admins.stream().map(admin->new GatewayProjectAdmin(projectId,admin.getId(),admin.getName())).collect(Collectors.toList());
           projectAdminService.saveBatch(projectAdmins);
       }
    }
    @Override
    public GatewayProjectVo getGatewayAuthProjectVoById(String id) {
        Assert.hasText(id, "工程主键不允许为空");
        GatewayProject authProject = this.getById(id);
        Assert.notNull(authProject, "工程不存在：" + id);
        GatewayProjectVo projectVo= BeanMapper.map(authProject, GatewayProjectVo.class);

        projectVo.setAdmins(projectAdminService.findAdminsByProjectId(id));
        return projectVo;
    }

    @Override
    public GatewayProjectVo getGatewayAuthProjectVoByProjectCode(String projectCode) {
        Assert.hasText(projectCode, "工程编码不允许为空");
        QueryWrapper<GatewayProject> eWrapper = new QueryWrapper<>();
        //查询工程ID
        eWrapper.eq("project_code", projectCode);
        GatewayProject authProject = this.getOne(eWrapper);
        Assert.notNull(authProject, "工程不存在：" + projectCode);
        GatewayProjectVo projectVo= BeanMapper.map(authProject, GatewayProjectVo.class);
        projectVo.setAdmins(projectAdminService.findAdminsByProjectId(projectVo.getId()));
        return projectVo;
    }



    private   MapperFacade getProjectBeanMapper() {
        if (this.mapper != null) {
            return mapper;
        }
        MapperFactory mapperFactory = new DefaultMapperFactory.Builder().mapNulls(false).build();

        mapperFactory.getConverterFactory().registerConverter("listToStringConverter", new ListToStringConverter());

        mapperFactory.classMap(GatewayProject.class, GatewayProjectDto.class)
                .fieldMap("annoUrl", "annoUrl").converter("listToStringConverter").add()
                .fieldMap("allowedOrigins", "allowedOrigins").converter("listToStringConverter").add()
                .fieldMap("allowedHeaders", "allowedHeaders").converter("listToStringConverter").add()
                .fieldMap("exposedHeaders", "exposedHeaders").converter("listToStringConverter").add()
                .fieldMap("allowedMethods", "allowedMethods").converter("listToStringConverter").add()
                .byDefault().register();

        this.mapper= mapperFactory.getMapperFacade();
        return mapper;
    }


    @Override
    public String getDbFieldCode() {
        return "project_code";
    }
}
